package com.ruoyi.crm.service.impl;

import java.io.Serializable;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.enums.AuditStatus;
import com.ruoyi.common.enums.erp.CrmFeeTypeEnum;
import com.ruoyi.common.enums.erp.CrmOrderProgessEnum;
import com.ruoyi.common.enums.flow.FlowTypeEnum;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.flow.FlowDTO;
import com.ruoyi.common.utils.flow.FlowParamsUtils;
import com.ruoyi.crm.domain.*;
import com.ruoyi.crm.mapper.CrmAcceptanceSheetMapper;
import com.ruoyi.crm.service.*;
import com.ruoyi.crm.strategy.CrmOrderClearDetailsStrategy;
import com.ruoyi.crm.strategy.CrmOrderContext;
import com.ruoyi.crm.utils.ThreadLocalUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.crm.mapper.CrmClearAccountMapper;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

/**
 * 项目结算表Service业务层处理
 *
 * @author ruoyi
 * @date 2024-12-13
 */
@Service
public class CrmClearAccountServiceImpl extends ServiceImpl<CrmClearAccountMapper, CrmClearAccount> implements ICrmClearAccountService {
    @Autowired
    private CrmClearAccountMapper crmClearAccountMapper;

    @Autowired
    private ICrmOrderRegisterService crmOrderRegisterService;

    @Autowired
    private ICrmTaskService crmTaskService;

    @Autowired
    private ICrmOrderCollectPayMoneyService crmOrderCollectPayMoneyService;

    @Autowired
    private CrmAcceptanceSheetMapper crmAcceptanceSheetMapper;


    @Autowired
    private ICrmOrderService crmOrderService;

    @Autowired
    private ICrmOrderClearDetailsService crmOrderClearDetailsService;

    @Autowired
    private ICrmCostService crmCostService;

    @Autowired
    private CrmOrderContext crmOrderContext;


    @Autowired
    private ICrmCustomerService crmCustomerService;

    /**
     * 查询项目结算表
     *
     * @param id 项目结算表主键
     * @return 项目结算表
     */
    @Override
    public CrmClearAccount selectCrmClearAccountById(String id) {
        CrmClearAccount crmClearAccount = crmClearAccountMapper.selectCrmClearAccountById(id);
        return this.buildCrmClearAccount(crmClearAccount);
    }

    /**
     * 查询项目结算表列表
     *
     * @param crmClearAccount 项目结算表
     * @return 项目结算表
     */
    @Override
    public List<CrmClearAccount> selectCrmClearAccountList(CrmClearAccount crmClearAccount) {
        return crmClearAccountMapper.selectList(null);
    }

    /**
     * 新增项目结算表
     *
     * @param crmClearAccount 项目结算表
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertCrmClearAccount(CrmClearAccount crmClearAccount) {
        crmClearAccount.setCreateTime(DateUtils.getNowDate());
        crmClearAccount.setCreateBy(SecurityUtils.getUsername());
        crmClearAccount.setId(IdWorker.getIdStr());

        String orderId = crmClearAccount.getOrderId();

        CrmOrder order = crmOrderService.getById(orderId);

        if (ObjectUtils.isEmpty(order)){
            throw new ServiceException("商机不存在，请刷新后重试！");
        }

        Integer integer = crmAcceptanceSheetMapper.selectCount(new LambdaQueryWrapper<CrmAcceptanceSheet>()
                .eq(CrmAcceptanceSheet::getOrderId, crmClearAccount.getOrderId())
                .eq(CrmAcceptanceSheet::getAuditStatus, AuditStatus.PASS.getCode()));

        if (integer <= 0) {
            throw new ServiceException("请先完善验收表信息,或者验收信息还未审核通过！");
        }

        List<CrmOrderClearDetails> detailsList = crmClearAccount.getDetailsList();

        detailsList.forEach(details -> {
            details.setId(IdWorker.getIdStr());
            details.setOrderClearId(crmClearAccount.getId());
            details.setUserId(SecurityUtils.getUserId());
            insertClearDetailsService(details);
        });
        crmOrderClearDetailsService.saveBatch(detailsList);

        try {
            // 保存结算费详情数据
            ThreadLocalUtils.set(FlowTypeEnum.FLOW_ORDER_CLEAR.getInfo() + ":" + crmClearAccount.getId(), crmClearAccount);
            FlowParamsUtils.start(crmClearAccount, "flow-order-clear", crmClearAccount.getId());

            if (AuditStatus.AWAIT_AUDIT.getCode().equals(crmClearAccount.getAuditStatus())){
                FlowParamsUtils.submit(crmClearAccount);
            }

            return crmClearAccountMapper.insert(crmClearAccount);
        } finally {
            ThreadLocalUtils.remove(FlowTypeEnum.FLOW_ORDER_CLEAR.getInfo() + ":" + crmClearAccount.getId());
        }
    }




    /**
     * 添加详情和费用数据
     */
    private void insertClearDetailsService(CrmOrderClearDetails crmOrderClearDetails){
        CrmOrderClearDetailsStrategy clearDetailsService = crmOrderContext.getClearDetailsService(crmOrderClearDetails.getDetailsType());

        if (ObjectUtils.isEmpty(clearDetailsService)){
            return;
        }

        List<String> applyIds = crmOrderClearDetails.getApplyIds();
        for (String applyId : applyIds) {
            CrmApplyClearDetails crmApplyClearDetails = new CrmApplyClearDetails();
            crmApplyClearDetails.setClearDetailsId(crmOrderClearDetails.getId());
            crmApplyClearDetails.setApplyId(applyId);
            clearDetailsService.insert(crmApplyClearDetails);
        }
    }

    /**
     * 获取项目结算表详细信息
     * @param orderId
     * @return
     */
    @Override
    public CrmClearAccount getInfoByOrderId(String orderId) {
        CrmClearAccount crmClearAccount = baseMapper.getInfoByOrderId(orderId);

        return this.buildCrmClearAccount(crmClearAccount);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean audit(CrmClearAccount crmClearAccount) {
        CrmClearAccount clearAccount = baseMapper.selectById(crmClearAccount);

        if (ObjectUtils.isEmpty(clearAccount)){
            throw new ServiceException("项目结算数据不存在，请刷新后重试");
        }

        CrmOrder order = crmOrderService.getById(clearAccount.getOrderId());

        if (ObjectUtils.isEmpty(order)){
            throw new ServiceException("商机数据不存在，请刷新后重试");
        }


        FlowParamsUtils.skip(crmClearAccount, "");

        if (AuditStatus.PASS.getCode().equals(crmClearAccount.getAuditStatus())){
            // 修改商机进度，立项成功则进度已结算
            order.setOrderId(crmClearAccount.getOrderId());
            order.setProgess(CrmOrderProgessEnum.SETTLEMENT_COMPLETED.getCode());
            crmOrderService.updateCrmOrderInfo(order);


        }

        return baseMapper.updateById(crmClearAccount) > 0;
    }

    private CrmClearAccount buildCrmClearAccount(CrmClearAccount crmClearAccount){
        if (ObjectUtils.isEmpty(crmClearAccount)){
            return null;
        }

        List<CrmOrderClearDetails> detailsList = crmClearAccount.getDetailsList();

        for (CrmOrderClearDetails details : detailsList) {
            CrmOrderClearDetailsStrategy clearDetailsService = crmOrderContext.getClearDetailsService(details.getDetailsType());

            if (ObjectUtils.isEmpty(clearDetailsService)){
                continue;
            }

            List<CrmApplyClearDetails> list = clearDetailsService.list(details.getId());
            List<String> applyIds = list.stream().map(CrmApplyClearDetails::getApplyId).collect(Collectors.toList());

            details.setApplyIds(applyIds);
        }
        return crmClearAccount;
    }

    /**
     * 修改项目结算表
     *
     * @param crmClearAccount 项目结算表
     * @return 结果
     */
    @Override
    public int updateCrmClearAccount(CrmClearAccount crmClearAccount) {
        crmClearAccount.setUpdateTime(DateUtils.getNowDate());
        crmClearAccount.setUpdateBy(SecurityUtils.getUsername());

        CrmClearAccount clearAccount = baseMapper.selectById(crmClearAccount.getId());

        if (ObjectUtils.isEmpty(clearAccount)){
            throw new ServiceException("项目结算不存在，请刷新后重试");
        }

        this.computeAmount(crmClearAccount);

        // 删除原来的项目明细
        crmOrderClearDetailsService.remove(new LambdaQueryWrapper<CrmOrderClearDetails>()
                .eq(CrmOrderClearDetails::getOrderClearId, crmClearAccount.getId()));

        this.saveDetails(crmClearAccount);

        try {
            ThreadLocalUtils.set(FlowTypeEnum.FLOW_ORDER_CLEAR.getInfo() + ":" + crmClearAccount.getId(), crmClearAccount);
            // 如果项目处于待提交状态，则直接修改
            if (AuditStatus.AWAIT_SUBMIT.getCode().equals(clearAccount.getAuditStatus())){

                // 如果新立项状态为提交，则执行流程
                if (AuditStatus.AWAIT_AUDIT.getCode().equals(crmClearAccount.getAuditStatus())) {
                    FlowParamsUtils.submit(crmClearAccount);
                }

                return crmClearAccountMapper.updateById(crmClearAccount);
            }


            // 如果当前项目处于待审核也直接修改
            if (AuditStatus.AWAIT_AUDIT.getCode().equals(clearAccount.getAuditStatus())){

                // 如果新结算状态为暂存，则删除流程
                if (AuditStatus.AWAIT_SUBMIT.getCode().equals(crmClearAccount.getAuditStatus())) {
                    FlowParamsUtils.remove(clearAccount.getInstanceId());
                    // 开启新流程
                    FlowParamsUtils.start(crmClearAccount, "flow-order-clear", crmClearAccount.getId());
                }

                return crmClearAccountMapper.updateById(crmClearAccount);
            }


            // 在审核中，则删除原来流程
            if (AuditStatus.IN_AUDIT.getCode().equals(clearAccount.getAuditStatus())){
                FlowParamsUtils.remove(clearAccount.getInstanceId());
            }

            // 开启新流程
            FlowParamsUtils.start(crmClearAccount, "flow-order-clear", crmClearAccount.getId());

            // 如果新立项状态为提交，则执行流程
            if (AuditStatus.AWAIT_AUDIT.getCode().equals(crmClearAccount.getAuditStatus())) {
                FlowParamsUtils.submit(crmClearAccount);
            }

            return crmClearAccountMapper.updateById(crmClearAccount);
        } finally {
            ThreadLocalUtils.remove(FlowTypeEnum.FLOW_ORDER_CLEAR.getInfo() + ":" + crmClearAccount.getId());
        }
    }


    /**
     * 新增项目详情
     * @param crmClearAccount
     */
    private void saveDetails(CrmClearAccount crmClearAccount){
        List<CrmOrderClearDetails> detailsList = crmClearAccount.getDetailsList();

        detailsList.forEach(item -> {
            item.setId(IdWorker.getIdStr());
            item.setOrderClearId(crmClearAccount.getId());
            item.setUserId(SecurityUtils.getUserId());

            CrmOrderClearDetailsStrategy clearDetailsService = crmOrderContext.getClearDetailsService(item.getDetailsType());

            if (ObjectUtils.isEmpty(clearDetailsService)){
                return;
            }

            // 删除结算明细中的费用出处
            clearDetailsService.remove(item.getId());
            List<String> applyIds = item.getApplyIds();
            for (String applyId : applyIds) {
                CrmApplyClearDetails crmApplyClearDetails = new CrmApplyClearDetails();
                crmApplyClearDetails.setClearDetailsId(item.getId());
                crmApplyClearDetails.setApplyId(applyId);
                clearDetailsService.insert(crmApplyClearDetails);
            }
        });

        crmOrderClearDetailsService.saveBatch(detailsList);
    }


    /**
     * 计算公司项目最终利润，利润率，费用总计
     * @param crmClearAccount
     */
    private void computeAmount(CrmClearAccount crmClearAccount){
        List<CrmOrderClearDetails> detailsList = crmClearAccount.getDetailsList();

        // 计算费用总计
        BigDecimal aggregationCharge = BigDecimal.ZERO;
        for (CrmOrderClearDetails clearDetails : detailsList) {
            // 选择了无，则直接跳过
            if ("1".equals(clearDetails.getIsRequired())) continue;

            aggregationCharge = aggregationCharge.add(ObjectUtils.isEmpty(clearDetails.getDetailsAmount()) ? BigDecimal.ZERO : clearDetails.getDetailsAmount());
        }
        crmClearAccount.setAggregationCharge(aggregationCharge);

        // 计算利润
        BigDecimal projectSum = crmClearAccount.getProjectSum();
        BigDecimal profit = projectSum.subtract(aggregationCharge);
        crmClearAccount.setProfit(profit);

        // 计算利润率
        BigDecimal profitMargin = profit.divide(projectSum, 2, RoundingMode.HALF_UP).multiply(new BigDecimal("100"));
        crmClearAccount.setProfitMargin(profitMargin);
    }


    /**
     * 批量删除项目结算表
     *
     * @param ids 需要删除的项目结算表主键
     * @return 结果
     */
    @Override
    public int deleteCrmClearAccountByIds(String[] ids) {
        return crmClearAccountMapper.deleteBatchIds(Arrays.asList(ids));
    }

    /**
     * 删除项目结算表信息
     *
     * @param id 项目结算表主键
     * @return 结果
     */
    @Override
    public int deleteCrmClearAccountById(String id) {
        return crmClearAccountMapper.deleteById(id);
    }

    /**
     * 当没有结算数据后，初始化结算表
     *
     * @param orderId
     * @return
     */
    @Override
    public CrmClearAccount orderClearInit(String orderId) {
        CrmClearAccount crmClearAccount = new CrmClearAccount();

        // 先获取立项表数据
        CrmOrderRegister crmOrderRegister = crmOrderRegisterService.selectCrmOrderRegisterByOrderId(orderId);

        if (ObjectUtils.isEmpty(crmOrderRegister)) {
            throw new ServiceException("请先填写立项表数据！");
        }

        // 从立项获取基础结算表数据
        crmClearAccount.setDeptId(crmOrderRegister.getDeptId());
        crmClearAccount.setProjectOn(crmOrderRegister.getProjectOn());
        crmClearAccount.setOrderId(crmOrderRegister.getOrderId());
        crmClearAccount.setCustomerId(crmOrderRegister.getCustomerId());
        crmClearAccount.setStartTime(new Date());
        crmClearAccount.setApplyUser(crmOrderRegister.getApplyUser());
        crmClearAccount.setPrincipalId(crmOrderRegister.getChargeUser());
        crmClearAccount.setProjectSum(crmOrderRegister.getProjectSum());
        crmClearAccount.setProfit(crmOrderRegister.getProfit());
        crmClearAccount.setProfitMargin(crmOrderRegister.getProfitMargin());

        // 获取立项的预计支出
        List<CrmOrderRegisterDetails> orderRegisterDetailsList = crmOrderRegister.getDetailsList();

        if (orderRegisterDetailsList.isEmpty()){
            return crmClearAccount;
        }

        // 获取付款数据支出
        List<CrmOrderPayDetails> payDetailsList = crmOrderCollectPayMoneyService.getPayDetailsListByOrderId(orderId);

        List<CrmOrderRegisterDetails> crmOrderRegisterDetailsListResult = new ArrayList<>();

        if (!payDetailsList.isEmpty()) {
            // 合并付款详情和立项详情，以类型为key
            Map<String, List<CrmOrderRegisterDetails>> orderRegisterDetailsMap = orderRegisterDetailsList.stream().collect(Collectors.groupingBy(CrmOrderRegisterDetails::getDetailsType));
            Map<String, List<CrmOrderPayDetails>> crmOrderPayDetailsMap = payDetailsList.stream().collect(Collectors.groupingBy(CrmOrderPayDetails::getDetailsType));

            crmOrderRegisterDetailsListResult = mergeMaps(orderRegisterDetailsMap, crmOrderPayDetailsMap);
        } else {
            crmOrderRegisterDetailsListResult = orderRegisterDetailsList;
        }

        // 转换成结算数据
        List<CrmOrderClearDetails> crmOrderClearDetailsList = crmOrderRegisterDetailsListResult.stream().map(item ->
                new CrmOrderClearDetails()
                        .setDetailsAmount(item.getDetailsAmount())
                        .setDetailsType(item.getDetailsType())
                        .setDetailsName(item.getDetailsName())
                        .setDetailsDesc(item.getDetailsDesc())
                        .setIsRequired(ObjectUtils.isEmpty(item.getDetailsAmount()) ? "1" : "0")
                        .setRemark(item.getRemark())
        ).collect(Collectors.toList());

        // 获取工单天数
        List<CrmTask> crmTaskList = crmTaskService.list(new LambdaQueryWrapper<CrmTask>()
                .eq(CrmTask::getOrderId, orderId)
                .eq(CrmTask::getAuditStatus, AuditStatus.PASS.getCode()));



        // 如果立项和付款处写了工单金额，不覆盖金额，只告知有几个实际工单
        if (!ObjectUtils.isEmpty(crmTaskList)) {
            BigDecimal totalActualDay = crmTaskList.stream()
                    .map(CrmTask::getActualDay)
                    .filter(Objects::nonNull) // 过滤掉 null 值
                    .reduce(BigDecimal.ZERO, BigDecimal::add);

            // 获取第一个工单明细, 并设置工单备注
            CrmOrderClearDetails crmOrderClearDetails = crmOrderClearDetailsList.stream().filter(item ->
                    CrmFeeTypeEnum.WORK_ORDER.getCode().equals(item.getDetailsType())).findFirst().get();
            crmOrderClearDetails.setDetailsDesc("现在 " + totalActualDay.doubleValue() + " 个工单");
            crmOrderClearDetails.setIsRequired("0");
        }


        // 获取差旅费信息
        List<CrmCost> crmCostList = crmCostService.list(new LambdaQueryWrapper<CrmCost>()
                .eq(CrmCost::getOrderId, crmClearAccount.getOrderId())
                .eq(CrmCost::getUserId, SecurityUtils.getUserId())
                .or()
                .eq(CrmCost::getApplyUserId, SecurityUtils.getUserId())
                .eq(CrmCost::getIsDispose, "1"));

        // 存在差旅费信息则最终以差旅费信息为主
        if (!ObjectUtils.isEmpty(crmCostList)){
            BigDecimal reduce = crmCostList.stream().map(CrmCost::getGrossAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
            CrmOrderClearDetails crmOrderClearDetails = crmOrderClearDetailsList.stream().filter(item ->
                    CrmFeeTypeEnum.BUSINESS_TRIP.getCode().equals(item.getDetailsType())).findFirst().get();
            crmOrderClearDetails.setDetailsAmount(reduce);
            crmOrderClearDetails.setIsRequired("0");
        }


        crmClearAccount.setDetailsList(crmOrderClearDetailsList);

        return crmClearAccount;
    }


    private static List<CrmOrderRegisterDetails> mergeMaps(
            Map<String, List<CrmOrderRegisterDetails>> orderRegisterDetailsMap,
            Map<String, List<CrmOrderPayDetails>> crmOrderPayDetailsMap
    ) {
        List<CrmOrderRegisterDetails> mergedList = new ArrayList<>();

        // 合并两个 Map 中具有相同 detailsType 的数据
        for (Map.Entry<String, List<CrmOrderRegisterDetails>> entry : orderRegisterDetailsMap.entrySet()) {
            String detailsType = entry.getKey();
            List<CrmOrderRegisterDetails> registerDetailsList = entry.getValue();
            List<CrmOrderPayDetails> payDetailsList = crmOrderPayDetailsMap.get(detailsType);

            // 调用辅助方法处理相同 detailsType 的数据合并
            mergedList.addAll(mergeDetails(registerDetailsList, payDetailsList, detailsType));
        }

        // 处理 crmOrderPayDetailsMap 中多出的 detailsType
        for (Map.Entry<String, List<CrmOrderPayDetails>> entry : crmOrderPayDetailsMap.entrySet()) {
            String detailsType = entry.getKey();
            if (!orderRegisterDetailsMap.containsKey(detailsType)) {
                List<CrmOrderPayDetails> payDetailsList = entry.getValue();
                // 对于多出的 detailsType，创建新的 CrmOrderRegisterDetails
                for (CrmOrderPayDetails payDetail : payDetailsList) {
                    mergedList.add(createRegisterDetailFromPayDetail(payDetail));
                }
            }
        }

        return mergedList;
    }

    /**
     * 合并具有相同 detailsType 的 CrmOrderRegisterDetails 和 CrmOrderPayDetails 数据。
     * 如果 detailsType 为 CrmFeeTypeEnum.OTHER.getCode()，则不覆盖，仅合并集合。
     *
     * @param registerDetailsList 注册详情列表
     * @param payDetailsList 支付详情列表
     * @param detailsType 当前处理的详情类型
     * @return 合并后的列表
     */
    private static List<CrmOrderRegisterDetails> mergeDetails(
            List<CrmOrderRegisterDetails> registerDetailsList,
            List<CrmOrderPayDetails> payDetailsList,
            String detailsType
    ) {
        List<CrmOrderRegisterDetails> mergedList = new ArrayList<>();

        // 如果 detailsType 为 OTHER 类型，直接合并集合
        if (CrmFeeTypeEnum.OTHER.getCode().equals(detailsType)) {
            if (registerDetailsList != null) {
                mergedList.addAll(registerDetailsList);
            }
            if (payDetailsList != null) {
                for (CrmOrderPayDetails payDetail : payDetailsList) {
                    mergedList.add(createRegisterDetailFromPayDetail(payDetail));
                }
            }
            return mergedList;
        }

        int maxSize = Math.max(
                registerDetailsList != null ? registerDetailsList.size() : 0,
                payDetailsList != null ? payDetailsList.size() : 0
        );

        for (int i = 0; i < maxSize; i++) {
            // 获取当前索引的注册详情，如果不存在则创建一个新的实例
            CrmOrderRegisterDetails registerDetail = i < (registerDetailsList != null ? registerDetailsList.size() : 0)
                    ? registerDetailsList.get(i)
                    : new CrmOrderRegisterDetails();

            // 设置 detailsType，如果尚未设置
            if (registerDetail.getDetailsType() == null) {
                registerDetail.setDetailsType(detailsType);
            }

            // 如果支付详情存在，覆盖相应的字段
            if (payDetailsList != null && i < payDetailsList.size()) {
                CrmOrderPayDetails payDetail = payDetailsList.get(i);
                registerDetail.setDetailsAmount(payDetail.getPayDetailsAmount());
                registerDetail.setDetailsName(payDetail.getPayDetailsName());
            }

            // 添加到合并列表
            mergedList.add(registerDetail);
        }

        return mergedList;
    }

    /**
     * 根据 CrmOrderPayDetails 创建一个新的 CrmOrderRegisterDetails。
     *
     * @param payDetail 支付详情对象
     * @return 新的注册详情对象
     */
    private static CrmOrderRegisterDetails createRegisterDetailFromPayDetail(CrmOrderPayDetails payDetail) {
        CrmOrderRegisterDetails registerDetail = new CrmOrderRegisterDetails();
        registerDetail.setDetailsType(payDetail.getDetailsType());
        registerDetail.setDetailsAmount(payDetail.getPayDetailsAmount());
        registerDetail.setDetailsName(payDetail.getPayDetailsName());
        return registerDetail;
    }


    public static void main(String[] args) {
        // 假数据 1：CrmOrderRegisterDetails
        CrmOrderRegisterDetails register1 = new CrmOrderRegisterDetails(
                "1", "哈哈A", new BigDecimal("10.00")
        );
        CrmOrderRegisterDetails register2 = new CrmOrderRegisterDetails(
                "2", "哈哈B", new BigDecimal("20.00")
        );
        CrmOrderRegisterDetails register3 = new CrmOrderRegisterDetails(
                "3", "哈哈c", new BigDecimal("30.00")
        );
        CrmOrderRegisterDetails register4 = new CrmOrderRegisterDetails(
                "7", "哈哈d", new BigDecimal("40.00")
        );
        CrmOrderRegisterDetails register5 = new CrmOrderRegisterDetails(
                "5", "哈哈f", new BigDecimal("50.00")
        );

        // 假数据 2：CrmOrderPayDetails
        CrmOrderPayDetails pay3 = new CrmOrderPayDetails(
                new BigDecimal("300.00"), "嘻嘻B", "1"
        );
        CrmOrderPayDetails pay1 = new CrmOrderPayDetails(
                new BigDecimal("100.00"), "嘻嘻A", "2"
        );
        CrmOrderPayDetails pay2 = new CrmOrderPayDetails(
                new BigDecimal("200.00"), "嘻嘻c", "3"
        );
        CrmOrderPayDetails pay4 = new CrmOrderPayDetails(
                new BigDecimal("400.00"), "嘻嘻d", "7"
        );


        Map<String, List<CrmOrderRegisterDetails>> orderRegisterDetailsMap = Arrays.asList(register1, register2, register3, register4, register5).stream()
                .collect(Collectors.groupingBy(CrmOrderRegisterDetails::getDetailsType));

        Map<String, List<CrmOrderPayDetails>> crmOrderPayDetailsMap = Arrays.asList(pay1, pay2, pay3, pay4).stream()
                .collect(Collectors.groupingBy(CrmOrderPayDetails::getDetailsType));

        List<CrmOrderRegisterDetails> result = mergeMaps(orderRegisterDetailsMap, crmOrderPayDetailsMap);

        System.out.println("合并后的结果：");
        result.forEach(System.out::println);
    }

    @Override
    public FlowDTO conversionObj(Serializable id) {
        CrmClearAccount crmClearAccount = baseMapper.getById(id);
        FlowDTO flowDTO = this.buildFlowDTO(crmClearAccount);
        return flowDTO;
    }


    @Override
    public FlowDTO conversionObjByLocal(Serializable id) {
        CrmClearAccount clearAccount = ThreadLocalUtils.get(FlowTypeEnum.FLOW_ORDER_CLEAR.getInfo() + ":" + id);
        CrmCustomer customer = crmCustomerService.getById(clearAccount.getCustomerId());
        clearAccount.setCustomerName(customer.getCustomerName());
        FlowDTO flowDTO = this.buildFlowDTO(clearAccount);
        return flowDTO;
    }

    private FlowDTO buildFlowDTO(CrmClearAccount clearAccount){
        FlowDTO flowDTO = new FlowDTO(clearAccount);
        Map<String, Object> businessValue = flowDTO.getBusinessValue();
        businessValue.put("项目名称", clearAccount.getProjectName());
        businessValue.put("客户名称", clearAccount.getCustomerName());
        businessValue.put("项目金额", clearAccount.getProjectSum());
        return flowDTO;
    }
}
